<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html><head><title>Programming in Lua : 14.1</title>
<link rel="stylesheet" type="text/css" href="pil.css">
</head>
<body>
<p class="warning">
<A HREF="contents.html"><IMG TITLE="Programming in Lua (first edition)" SRC="capa.jpg" ALT="" ALIGN="left"></A>This first edition was written for Lua 5.0. While still largely relevant for later versions, there are some differences.<BR>The third edition targets Lua 5.2 and is available at <A HREF="http://www.amazon.com/exec/obidos/ASIN/859037985X/theprogrammil3-20">Amazon</A> and other bookstores.<BR>By buying the book, you also help to <A HREF="../donations.html">support the Lua project</A>.
</p>
<table width="100%" class="nav">
<tr>
<td width="10%" align="left"><a href="14.html"><img border="0" src="left.png" alt="Previous"></a></td>
<td width="80%" align="center"><a href="contents.html"><font face="Helvetica,Arial,sanserif">
<font color="gray">Programming in </font><font color="blue"> Lua</font>
</font></a></td>
<td width="10%" align="right"><a href="14.2.html"><img border="0" src="right.png" alt="Next"></a></td>
</tr>
<tr>
<td width="10%" align="left"></td>
<td width="80%" align="center"><a href="contents.html#P2">Part II. Tables and Objects</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a href="contents.html#14">Chapter 14. The Environment</a></td>
<td width="10%" align="right"></td></tr>
</table>
<hr/>
<p><h2>14.1 &ndash; Accessing Global Variables with Dynamic Names</h2>

<p>Usually, assignment is enough for getting and setting global variables.
However, often we need some form of meta-programming,
such as when we need to manipulate a global variable whose
name is stored in another variable,
or somehow computed at run time.
To get the value of this variable,
many programmers are tempted to write something like
<pre>
    loadstring("value = " .. varname)()
</pre>
or
<pre>
    value = loadstring("return " .. varname)()
</pre>
If <code>varname</code> is <code>x</code>, for instance,
the concatenation will result in <code>"return x"</code>
(or <code>"value = x"</code>, with the first form),
which when run achieves the desired result.
However, such codes involve the creation and compilation of a new chunk
and lots of extra work.
You can accomplish the same effect with the following code,
which is more than an order of magnitude more efficient
than the previous one:
<pre>
    value = _G[varname]
</pre>
Because the environment is a regular table,
you can simply index it with the desired key (the variable name).

<p>In a similar way,
you can assign to a global variable whose name is computed dynamically,
writing <code>_G[varname] = value</code>.
Beware, however:
Some programmers get a little excited with these functions
and end up writing code like
<code>_G["a"] = _G["var1"]</code>,
which is just a complicated way to write <code>a = var1</code>.

<p><pre>

</pre>

<p>A generalization of the previous problem
is to allow fields in a dynamic name,
such as <code>"io.read"</code> or <code>"a.b.c.d"</code>.
We solve this problem with a loop,
which starts at <code>_G</code>
and evolves field by field:
<pre>
    function getfield (f)
      local v = _G    -- start with the table of globals
      for w in string.gfind(f, "[%w_]+") do
        v = v[w]
      end
      return v
    end
</pre>
We rely on <code>gfind</code>, from the <code>string</code> library,
to iterate over all words in <code>f</code>
(where "word" is a sequence of one or more
alphanumeric characters and underscores).

<p>The corresponding function to set fields is a little more complex.
An assignment like
<pre>
    a.b.c.d.e = v
</pre>
is exactly equivalent to
<pre>
    local temp = a.b.c.d
    temp.e = v
</pre>
That is, we must retrieve up to the last name;
we must handle the last field separately.
The new <code>setfield</code> function also creates intermediate tables
in a path when they do not exist:
<pre>
    function setfield (f, v)
      local t = _G    -- start with the table of globals
      for w, d in string.gfind(f, "([%w_]+)(.?)") do
        if d == "." then      -- not last field?
          t[w] = t[w] or {}   -- create table if absent
          t = t[w]            -- get the table
        else                  -- last field
          t[w] = v            -- do the assignment
        end
      end
    end
</pre>
This new pattern captures the field name in variable <code>w</code>
and an optional following dot in variable <code>d</code>.
If a field name is not followed by a dot then it is the last name.
(We will discuss pattern matching at great length
in <a href="20.html#StringLib">Chapter 20</a>.)

<p>With the previous functions, the call
<pre>
    setfield("t.x.y", 10)
</pre>
creates a global table <code>t</code>,
another table <code>t.x</code>,
and assigns 10 to <code>t.x.y</code>:
<pre>
    print(t.x.y)     --> 10
    print(getfield("t.x.y"))   --> 10
</pre>

<hr/>
<table width="100%" class="nav">
<tr valign="top">
<td width="90%" align="left">
<small>
  Copyright &copy; 2003&ndash;2004 Roberto Ierusalimschy.  All rights reserved.
</small>
</td>
<td width="10%" align="right"><a href="14.2.html"><img border="0" src="right.png" alt="Next"></a></td>
</tr>
</table>


</body></html>

